<html>
<head><meta charset="utf-8"><title>Help debugging a trait issue · t-compiler/rust-analyzer · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/index.html">t-compiler/rust-analyzer</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Help.20debugging.20a.20trait.20issue.html">Help debugging a trait issue</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="196074601"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Help%20debugging%20a%20trait%20issue/near/196074601" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Adam Bratschi-Kaye (he) <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Help.20debugging.20a.20trait.20issue.html#196074601">(May 02 2020 at 23:17)</a>:</h4>
<p>Hey, I was trying to debug <a href="https://github.com/rust-analyzer/rust-analyzer/issues/4132" title="https://github.com/rust-analyzer/rust-analyzer/issues/4132">https://github.com/rust-analyzer/rust-analyzer/issues/4132</a> and seem to have a simple reproduction here:</p>
<div class="codehilite"><pre><span></span><code><span class="k">struct</span> <span class="nc">A</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">x</span>: <span class="nc">T</span><span class="p">,</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">trait</span><span class="w"> </span><span class="n">Constraint</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="k">impl</span><span class="w"> </span><span class="n">Constraint</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="kt">i32</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>

<span class="k">trait</span><span class="w"> </span><span class="n">MyTrait</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">transform</span><span class="p">(</span><span class="n">x</span>: <span class="nc">T</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="p">;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
<span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span>: <span class="nc">Constraint</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MyTrait</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">A</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">transform</span><span class="p">(</span><span class="n">x</span>: <span class="nc">T</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">A</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">A</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">A</span>::<span class="n">transform</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>


<p>In this case rust-analyzer shows the type of <code>a</code> in <code>main</code>  as <code>A&lt;{unknown}&gt;</code>, but it's able to infer <code>a: A&lt;i32&gt;</code> if I remove the <code>Constraint</code> trait or specify <code>1i32</code>. Any tips on how to further debug this?</p>
<p>One thing I've seen so far that I don't understand is that at some point in <a href="https://github.com/rust-analyzer/rust-analyzer/blob/89e1f97515c36ab97bd378d972cabec0feb6d77e/crates/ra_hir_ty/src/infer.rs#L307" title="https://github.com/rust-analyzer/rust-analyzer/blob/89e1f97515c36ab97bd378d972cabec0feb6d77e/crates/ra_hir_ty/src/infer.rs#L307"><code>resolve_obligations_as_possible</code></a> we try to  resolve the obligation </p>
<div class="codehilite"><pre><span></span><code><span class="n">Implements</span><span class="p">(</span><span class="n">A</span><span class="o">&lt;</span><span class="n">_</span><span class="o">&gt;</span>: <span class="nc">MyTrait</span><span class="o">&lt;</span><span class="n">_</span><span class="o">&gt;</span><span class="p">)</span><span class="w"></span>
</code></pre></div>


<p>which should have a unique solution of <code>i32</code>, but the result we're getting is <code>Ambig(Unknown}</code>. Plugging the same program into the chalk repl seems like it should work fine:</p>
<div class="codehilite"><pre><span></span><code><span class="o">?-</span><span class="w"> </span><span class="n">program</span><span class="w"></span>
<span class="n">Enter</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">program</span><span class="p">;</span><span class="w"> </span><span class="n">press</span><span class="w"> </span><span class="n">Ctrl</span><span class="o">-</span><span class="n">D</span><span class="w"> </span><span class="n">when</span><span class="w"> </span><span class="n">finished</span><span class="w"></span>
<span class="o">|</span><span class="w"> </span><span class="k">struct</span> <span class="nc">A</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="o">|</span><span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="n">Constraint</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="o">|</span><span class="w"> </span><span class="k">impl</span><span class="w"> </span><span class="n">Constraint</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="kt">i32</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="o">|</span><span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="n">MyTrait</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="o">|</span><span class="w"> </span><span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MyTrait</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">A</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="k">where</span><span class="w"> </span><span class="n">T</span>: <span class="nc">Constraint</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="o">|</span><span class="w"></span>
<span class="o">?-</span><span class="w"> </span><span class="n">exists</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="n">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">A</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>: <span class="nc">MyTrait</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="n">Unique</span><span class="p">;</span><span class="w"> </span><span class="n">substitution</span><span class="w"> </span><span class="p">[</span><span class="o">?</span><span class="mi">0</span><span class="w"> </span>:<span class="o">=</span><span class="w"> </span><span class="n">Int</span><span class="p">(</span><span class="n">I32</span><span class="p">),</span><span class="w"> </span><span class="o">?</span><span class="mi">1</span><span class="w"> </span>:<span class="o">=</span><span class="w"> </span><span class="n">Int</span><span class="p">(</span><span class="n">I32</span><span class="p">)],</span><span class="w"> </span><span class="n">lifetime</span><span class="w"> </span><span class="n">constraints</span><span class="w"> </span><span class="p">[]</span><span class="w"></span>
</code></pre></div>


<p>Any advice in particular on how to further check what statements are available to chalk and why it can't seem to resolve this obligation?</p>



<a name="196076001"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Help%20debugging%20a%20trait%20issue/near/196076001" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Florian Diebold <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Help.20debugging.20a.20trait.20issue.html#196076001">(May 03 2020 at 00:02)</a>:</h4>
<p>to model this in Chalk the way rust-analyzer would, you need to mark the traits <code>#[non_enumerable]</code>. we don't allow open-ended searches of all impls, that's why this doesn't work</p>



<a name="196076066"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Help%20debugging%20a%20trait%20issue/near/196076066" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Florian Diebold <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Help.20debugging.20a.20trait.20issue.html#196076066">(May 03 2020 at 00:03)</a>:</h4>
<p>I'm reasonably sure rustc also only does this for integer variables, and the problem is that Chalk doesn't know about integer variables yet</p>



<a name="196076413"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Help%20debugging%20a%20trait%20issue/near/196076413" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Help.20debugging.20a.20trait.20issue.html#196076413">(May 03 2020 at 00:14)</a>:</h4>
<p>This looks like either integer fallback or "inference guessing" (where it eagerly selects the only remaining impl that could apply) at work</p>



<a name="196092977"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Help%20debugging%20a%20trait%20issue/near/196092977" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Adam Bratschi-Kaye (he) <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Help.20debugging.20a.20trait.20issue.html#196092977">(May 03 2020 at 09:13)</a>:</h4>
<p>Thanks <span class="user-mention" data-user-id="129457">@Florian Diebold</span>, that makes sense. If I add the <code>#[non_enumerable]</code> tag then chalk doesn't provide a solution:</p>
<div class="codehilite"><pre><span></span><code><span class="k">struct</span> <span class="nc">A</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="cp">#[non_enumerable]</span><span class="w"></span>
<span class="k">trait</span><span class="w"> </span><span class="n">Constraint</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="cp">#[non_enumerable]</span><span class="w"></span>
<span class="k">trait</span><span class="w"> </span><span class="n">MyTrait</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="k">impl</span><span class="w"> </span><span class="n">Constraint</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="kt">i32</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MyTrait</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">A</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="k">where</span><span class="w"> </span><span class="n">T</span>: <span class="nc">Constraint</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>

<span class="o">?-</span><span class="w"> </span><span class="n">exists</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="n">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">A</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>: <span class="nc">MyTrait</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="n">Ambiguous</span><span class="p">;</span><span class="w"> </span><span class="n">no</span><span class="w"> </span><span class="n">inference</span><span class="w"> </span><span class="n">guidance</span><span class="w"></span>
</code></pre></div>


<p>But now I'm confused as to why it doesn't at least determine that <code>T</code> and <code>U</code> should be the same type. It is able to do that if the implementation for <code>MyTrait</code> on <code>A</code> doesn't have the condition <code>T: Constraint</code>:</p>
<div class="codehilite"><pre><span></span><code><span class="k">struct</span> <span class="nc">A</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="cp">#[non_enumerable]</span><span class="w"></span>
<span class="k">trait</span><span class="w"> </span><span class="n">Constraint</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="cp">#[non_enumerable]</span><span class="w"></span>
<span class="k">trait</span><span class="w"> </span><span class="n">MyTrait</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="k">impl</span><span class="w"> </span><span class="n">Constraint</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="kt">i32</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MyTrait</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">A</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>

<span class="o">?-</span><span class="w"> </span><span class="n">exists</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="n">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">A</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>: <span class="nc">MyTrait</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="n">Unique</span><span class="p">;</span><span class="w"> </span><span class="k">for</span><span class="o">&lt;?</span><span class="n">U0</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">substitution</span><span class="w"> </span><span class="p">[</span><span class="o">?</span><span class="mi">0</span><span class="w"> </span>:<span class="o">=</span><span class="w"> </span><span class="o">^</span><span class="mf">0.0</span><span class="p">,</span><span class="w"> </span><span class="o">?</span><span class="mi">1</span><span class="w"> </span>:<span class="o">=</span><span class="w"> </span><span class="o">^</span><span class="mf">0.0</span><span class="p">],</span><span class="w"> </span><span class="n">lifetime</span><span class="w"> </span><span class="n">constraints</span><span class="w"> </span><span class="p">[]</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="196093188"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Help%20debugging%20a%20trait%20issue/near/196093188" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Florian Diebold <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Help.20debugging.20a.20trait.20issue.html#196093188">(May 03 2020 at 09:19)</a>:</h4>
<p>Hmm I'm not sure, actually, that may require some debugging</p>



<a name="196093346"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Help%20debugging%20a%20trait%20issue/near/196093346" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Adam Bratschi-Kaye (he) <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Help.20debugging.20a.20trait.20issue.html#196093346">(May 03 2020 at 09:23)</a>:</h4>
<p>I'm happy to try looking into it.</p>



<a name="196093435"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Help%20debugging%20a%20trait%20issue/near/196093435" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Florian Diebold <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Help.20debugging.20a.20trait.20issue.html#196093435">(May 03 2020 at 09:25)</a>:</h4>
<p>not sure if you were using the recursive solver or the SLG solver there, if it was in the REPL it was probably SLG. Maybe the problem exists in both, but it'll surely require different fixes</p>



<a name="196093577"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Help%20debugging%20a%20trait%20issue/near/196093577" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Florian Diebold <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Help.20debugging.20a.20trait.20issue.html#196093577">(May 03 2020 at 09:29)</a>:</h4>
<p>oh, and if you want to look into it: (I don't know how familiar you are with Chalk, so) what I'd do is add a test for it in the Chalk repo, run it with <code>CHALK_DEBUG=2</code> (I just do that by calling <code>set_env</code> at the beginning of the test), and see what happens. Also probably ask about it over in #wg-traits ;)</p>



<a name="196097563"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Help%20debugging%20a%20trait%20issue/near/196097563" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Adam Bratschi-Kaye (he) <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Help.20debugging.20a.20trait.20issue.html#196097563">(May 03 2020 at 11:06)</a>:</h4>
<p>Thanks for the tips, I'm indeed not familiar with chalk. I was just using the repl by doing <code>cargo run</code> in the chalk repo, so if SLG is the default then that's what I had.</p>



<a name="196278022"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Help%20debugging%20a%20trait%20issue/near/196278022" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Adam Bratschi-Kaye (he) <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Help.20debugging.20a.20trait.20issue.html#196278022">(May 05 2020 at 08:06)</a>:</h4>
<p>Here's the thread in wg-traits: <a href="#narrow/stream/144729-wg-traits/topic/More.20guidance.20for.20an.20ambiguous.20query" title="#narrow/stream/144729-wg-traits/topic/More.20guidance.20for.20an.20ambiguous.20query">https://rust-lang.zulipchat.com/#narrow/stream/144729-wg-traits/topic/More.20guidance.20for.20an.20ambiguous.20query</a></p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>